package io.plus.engine.utils.lock_capable_task;

import lombok.Data;

import java.util.concurrent.*;

@Data
public class LockCapableTaskThreadPoolExecutor extends ThreadPoolExecutor {

    private String name = null;

    /**
     * @param keepAliveTime 单位: 秒
     */
    public LockCapableTaskThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, BlockingQueue<Runnable> runnableQueue, ThreadFactory threadFactory, String name) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, runnableQueue, threadFactory);
        this.name = name;
    }

    public LockCapableTaskThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, BlockingQueue<Runnable> runnableQueue, ThreadFactory threadFactory, String name, RejectedExecutionHandler rejectedExecutionHandler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, runnableQueue, threadFactory, rejectedExecutionHandler);
        this.name = name;
    }

    @Override
    public <R> Future<R> submit(Runnable runnable, R result) {
        if (checkBeforeExecute(runnable)) {
            Future<R> future = super.submit(runnable, result);
            return future;
        } else {
            return null;
        }
    }

    @Override
    public void execute(Runnable runnable) {
        if (!(runnable instanceof AbstractTask)) {
            super.execute(runnable);
        } else {
            AbstractTask synRunnable = (AbstractTask) runnable;
            if (synRunnable.executed) {
                return;
            }
            boolean tryLock = synRunnable.runnableLock.tryLock();
            if (tryLock) {
                try {
                    if (synRunnable.executed) {
                        return;
                    }
                    synRunnable.executed = true;
                    super.execute(runnable);
                } finally {
                    synRunnable.runnableLock.unlock();
                }
            } else {
                return;
            }
        }

    }

    private boolean checkBeforeExecute(Runnable runnable) {
        /**
         * 如果不是[特定的Task]则立即执行
         */
        if (!(runnable instanceof AbstractTask)) {
            return true;
        } else {
            AbstractTask synRunnable = (AbstractTask) runnable;
            if (synRunnable.executed) {
                return false;
            }
            boolean tryLock = synRunnable.runnableLock.tryLock();
            if (tryLock) {
                try {
                    if (synRunnable.executed) {
                        return false;
                    }
                    /**
                     * 获取写锁成功才允许执行
                     */
                    synRunnable.executed = true;
                    return true;
                } finally {
                    synRunnable.runnableLock.unlock();
                }
            } else {
                return false;
            }
        }
    }


}
